package com.zgw.his.emr.util;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.ArrayList;
import java.util.List;

/**
 * 类的反射方法集
 * 
 * 
 */
public class RefMethod {

	/**
	 * 得到某个对象的属性
	 * 
	 * @param owner
	 * @param fieldName
	 * @return
	 * @throws Exception
	 */
	public static Object getProperty(Object owner, String fieldName)
			throws Exception {
		Class ownerClass = owner.getClass();
		Object property = new Object();
		Field field = ownerClass.getField(fieldName);
		property = field.get(owner);

		return property;
	}

	public static Class getFieldClassType(Class clazz, String fieldName) {
		try {
			Field field = clazz.getDeclaredField(fieldName);
			return field.getType();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return Long.class;
	}

	/**
	 * 得到某个类的静态属性
	 * 
	 * @param className
	 * @param fieldName
	 * @return
	 * @throws Exception
	 */
	public static Object getStaticProperty(Class className, String fieldName)
			throws Exception {
		Field field = className.getField(fieldName);
		Object property = field.get(className);

		return property;
	}

	/**
	 * 执行某对象的方法,如果方法为无参方法,那就把传入的args的length设为0或者直接传入NULL,下同
	 * 调用此方法需注意一点,传入参数的类的类型必须和该方法所定义的参数的类的类型完全一致,
	 * <p>
	 * 否则会抛出 NoSuchMethodException异常
	 */
	@SuppressWarnings("unchecked")
	public static Object invokeMethod(Object owner, String methodName,
			Object[] args) {
		Class ownerClass = owner.getClass();
		Object result = null;
		if (args != null) {
			Class[] argsClass = new Class[args.length];
			for (int i = 0, j = args.length; i < j; i++) {
				argsClass[i] = args[i].getClass();
			}
			Method method;
			try {
				method = ownerClass.getMethod(methodName, argsClass);
				result = method.invoke(owner, args);
			} catch (Exception e) {
				e.printStackTrace();
			}
			return result;
		} else {
			args = new Object[0];
			Class[] argsClass = new Class[0];
			Method method;
			try {
				method = ownerClass.getMethod(methodName, argsClass);
				result = method.invoke(owner, args);
			} catch (Exception e) {
				e.printStackTrace();
			}
			return result;
		}
	}

	/**
	 * 利用反射机制执行方法,当参数只有一个时调用此方法,不能执行参数为Object类型的方法
	 * 
	 * @param owner
	 * @param methodName
	 * @param arg
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static Object invokeMethod(Object owner, String methodName,
			Object arg) {
		Class ownerClass = owner.getClass();
		Object result = null;
		if (arg != null) {
			Object[] args = { arg };
			Class argsClass = arg.getClass();
			// if (argsClass.equals(Long.class))
			// argsClass = Long.TYPE;
			// else if (argsClass.equals(Integer.class))
			// argsClass = Integer.TYPE;
			try {
				Method method = ownerClass.getMethod(methodName,
						new Class[] { argsClass });
				result = method.invoke(owner, args);
			} catch (Exception e) {
				e.printStackTrace();
			}
			return result;
		} else {
			Object[] args = new Object[0];
			Class[] argsClass = new Class[0];
			try {
				Method method = ownerClass.getMethod(methodName, argsClass);
				result = method.invoke(owner, args);
			} catch (Exception e) {
				e.printStackTrace();
			}
			return result;
		}
	}

	/**
	 * 执行持久类中Set方法
	 * 
	 * @param owner
	 * @param methodName
	 * @param args
	 */
	@SuppressWarnings("unchecked")
	public static void invokeSetMethod(Object owner, String methodName,
			Object args) {
		if (args == null)
			return;
		Object[] object = { args };
		Class ownerClass = owner.getClass();
		Class argsClass = args.getClass();
		if (argsClass.equals(byte[].class))
			argsClass = byte[].class;
		Method method;
		try {
			method = ownerClass
					.getMethod(methodName, new Class[] { argsClass });
			method.invoke(owner, object);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * <p>
	 * 执行持久类中set为null的方法,使用时需要注意的是不是参数argType传入null， 而是argType必须为你所执行的方法的参数类型
	 * </p>
	 * 
	 * @param owner
	 * @param methodName
	 *            方法名称
	 * @param argType
	 *            参数的class类型
	 */
	@SuppressWarnings("unchecked")
	public static void invokeSetMethod(Object owner, String methodName,
			Class argType) {
		Class ownerClass = owner.getClass();
		Method method;
		try {
			method = ownerClass.getMethod(methodName, new Class[] { argType });
			method.invoke(owner, new Object[] { null });
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 执行持久类中Get方法
	 * 
	 * @param owner
	 * @param methodName
	 */
	@SuppressWarnings("unchecked")
	public static Object invokeGetMethod(Object owner, String methodName) {
		Class ownerClass = owner.getClass();
		Object result = null;
		try {
			Method method = ownerClass.getMethod(methodName, new Class[] {});
			result = method.invoke(owner, new Object[] {});
		} catch (Exception e) {
			// e.printStackTrace();
		}
		return result;
	}

	/**
	 * 执行Object中方法,只适用单个参数的方法
	 * 
	 * @param service
	 * @param methodName
	 * @param param
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static Object invokeObjectMethod(Object service, String methodName,
			Object param) {
		Object result = null;
		try {
			Class ownerClass = service.getClass();
			Method method = ownerClass.getMethod(methodName,
					new Class[] { Object.class });
			result = method.invoke(service, new Object[] { param });
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 执行某个类对象的静态方法
	 * 
	 * @param className
	 *            此对象的class
	 * @param methodName
	 *            静态方法名称
	 * @param args
	 *            方法参数
	 * @return 返回结果，void方法返回null
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static Object invokeStaticMethod(Class className, String methodName,
			Object[] args) throws Exception {
		Class[] argsClass = new Class[args.length];
		for (int i = 0, j = args.length; i < j; i++) {
			argsClass[i] = args[i].getClass();
		}
		Method method = className.getMethod(methodName, argsClass);

		return method.invoke(null, args);
	}

	/**
	 * 
	 * 新建类的实例
	 * 
	 * @param className
	 *            类的Class
	 * @param args
	 *            实例化此类时构造函数的参数
	 * @return 返回此类的实例
	 */
	@SuppressWarnings("unchecked")
	public static Object newInstance(Class className, Object[] args) {
		Object result = null;
		if (args != null) {
			Class[] argsClass = new Class[args.length];
			for (int i = 0, j = args.length; i < j; i++) {
				argsClass[i] = args[i].getClass();
			}
			try {
				Constructor cons = className.getConstructor(argsClass);
				result = cons.newInstance(args);
			} catch (Exception e) {
				e.printStackTrace();
			}
			return result;
		} else {
			try {
				Constructor cons = className.getConstructor(new Class[] {});
				result = cons.newInstance(new Object[] {});
			} catch (Exception e) {
				e.printStackTrace();
			}
			return result;
		}
	}

	/**
	 * 判断是否为某个类的实例
	 * 
	 * @param obj
	 *            指定的对象
	 * @param cls
	 *            类的类型
	 * @return true为是这个类的实例
	 */
	public static boolean isInstance(Object obj, Class cls) {
		return cls.isInstance(obj);
	}

	/**
	 * 得到数组中的某个元素
	 * 
	 * @param array
	 *            数组对象
	 * @param index
	 *            元素在数组中的索引
	 * @return 指定索引在数组中的元素
	 */
	public Object getByArray(Object array, int index) {
		return Array.get(array, index);
	}

	/**
	 * 
	 * @param list
	 * @return
	 * @throws Exception
	 */
	public static List CopyToNewList(List list) {
		List returnList = new ArrayList();
		if (list != null) {
			try {
				for (Object obj : list) {
					Object newObj = CopyToNewLenObj(obj,
							newInstance(obj.getClass(), null));

					returnList.add(newObj);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return returnList;
	}

	/**
	 * 对象拷贝(从属性少的对象到属性多的对象)
	 * 
	 * @param old
	 * @param newObj
	 *            old对象包含 所有 newObj对象的属性
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static Object CopyToNewLenObj(Object old, Object newObj)
			throws Exception {
		Class oldClass = old.getClass();
		Field ff[] = oldClass.getDeclaredFields();
		for (int i = 0; i < ff.length; i++) {
			Field f = ff[i];// 取出每一个属性，如deleteDate
			Method m = oldClass.getMethod(gainGetMethod(f.getName()));// 方法getDeleteDate
			Object obj = m.invoke(old);// 取出属性值
			if (obj != null) {
				if (obj.getClass() == Timestamp.class) {
					Calendar calendar = Calendar.getInstance();
					calendar.setTime((Timestamp) obj);
					invokeSetMethod(newObj, gainSetMethod(f.getName()),
							calendar.getTime());
				} else {
					// f.set(newObj, obj);
					invokeSetMethod(newObj, gainSetMethod(f.getName()), obj);
				}
			}
		}
		return newObj;
	}

	/**
	 * 对象拷贝(从属性多的对象到属性少的对象)
	 * 
	 * @param old
	 * @param newObj
	 *            newObj对象包含 所有 old对象的属性
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static Object CopyToNewShortObj(Object old, Object newObj)
			throws Exception {
		Class oldClass = old.getClass();
		Class newClass = newObj.getClass();
		Field ff[] = newClass.getDeclaredFields();
		for (int i = 0; i < ff.length; i++) {
			Field f = ff[i];// 取出每一个属性，如deleteDate
			Method m = oldClass.getMethod(gainGetMethod(f.getName()));// 方法getDeleteDate
			Object obj = m.invoke(old);// 取出属性值
			if (obj != null) {
				if (obj.getClass() == Timestamp.class) {
					Calendar calendar = Calendar.getInstance();
					calendar.setTime((Timestamp) obj);
					invokeSetMethod(newObj, gainSetMethod(f.getName()),
							calendar.getTime());
				} else if (obj.getClass() == java.sql.Date.class) {
					Calendar calendar = Calendar.getInstance();
					calendar.setTime((java.sql.Date) obj);
					invokeSetMethod(newObj, gainSetMethod(f.getName()),
							calendar.getTime());
				} else {
					// f.set(newObj, obj);
					invokeSetMethod(newObj, gainSetMethod(f.getName()), obj);
				}
			}
		}
		return newObj;
	}

	/**
	 * 将字符串的第一个字符大字
	 * 
	 * @param inString
	 *            传入的字符串
	 * @return 返回处理后的字符串
	 */
	public static String upperCaseFirst(String inString) {
		inString = inString.trim();
		String temp = inString.substring(0, 1);
		return temp.toUpperCase() + inString.substring(1, inString.length());
	}

	public static String gainGetMethod(String fieldName) {
		return "get" + upperCaseFirst(fieldName);
	}

	public static String gainSetMethod(String fieldName) {
		return "set" + upperCaseFirst(fieldName);
	}

}
